/*
 *      dilca-manager.c
 *      
 *      Copyright 2009 Daniele Ricci <denn86@gmail.com>, Luca Saccagi <luksak86@gmail.com>
 *      
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 2 of the License, or
 *      (at your option) any later version.
 *      
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *      
 *      You should have received a copy of the GNU General Public License
 *      along with this program; if not, write to the Free Software
 *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *      MA 02110-1301, USA.
 */
#define _VERSION "dilca - Manager (v0.0.1)"
#define _VERSION1 "0.0.1"


#include <libidxp.h>
#include "lightlog.c"


#define DILCA_MAX_HOSTS 100

#ifdef _WIN32
#define MOVECMD "move "
#define RMCMD "del "
#else
#define MOVECMD "mv "
#define RMCMD "rm "
#endif

void version(int argc, char **argv);
int dilca_configuration_load(char *configuration_path);
int dilca_crn_load(char *hosts_path, char CRN_ip[DILCA_MAX_HOSTS][255], char CRN_port[DILCA_MAX_HOSTS][255]);
int dilca_dir_polling(char *dir);
int dilca_file_readall(char *filename);
bool dilca_file_move(char *destination, char *source);
bool dilca_custom_function_rs(IdxpConnection *connection,IdxpChannel *channel,IdxpFrame *frame, axlPointer data);


char dilca_dir_tmp[255];
char dilca_dir_hpsign[255];
char dilca_dir_send[255];
char dilca_dir_react[255];
int  dilca_polling;
int  dilca_reallocation_size;
int  dilca_retry;

int main(int argc, char **argv){
        IdxpConnection *listener = NULL;
		IdxpConnection *connection[DILCA_MAX_HOSTS];
        IdxpChannel *channel[DILCA_MAX_HOSTS];
        char CRN_ip[DILCA_MAX_HOSTS][255];
        char CRN_port[DILCA_MAX_HOSTS][255];
        int host_number=0;
        int i=0;	

		version(argc,argv);
        IDXPLIB

	/* Loading configurations */
        (argc==6) ? idxp_configuration_load(argv[1],NULL) : (printf("\nUsage: %s <idxp-conf> <dilca-conf> <crn-conf> <listen-add> <listen-port>\n",argv[0]) , exit(-1));
        dilca_configuration_load(argv[2]);
		host_number = dilca_crn_load(argv[3],CRN_ip,CRN_port);

	/* Setting Business Logic */
        idxp_custom_extended_server_set(dilca_custom_function_rs);

	/* Starting Listener */
        listener = idxp_connection_new(listener,argv[4],argv[5]);

	/* Starting CRN Broadcast Connection */
	for(i=0;i<host_number;i++) {
                //printf("%s:%s\n",CRN_ip[i],CRN_port[i]);
                connection[i]=idxp_connection_start(connection[i],CRN_ip[i],CRN_port[i],idxp_configuration_get("usr",NULL),idxp_configuration_get("pw",NULL));
                channel[i]=idxp_channel_new(connection[i],1,"localhost",0,"client",idxp_configuration_get("uri",NULL),idxp_configuration_get("fqdn",NULL),"extended");
        }

	/* Begin polling for initiator side */
	dilca_dir_polling(dilca_dir_send);

    idxp_listener_wait();
    idxp_exit();

        return 1;
}

#ifdef _WIN32
static void version(int argc, char **argv){
#else
void version(int argc, char **argv){
#endif
	if(argc <= 1) return;
	if(strcmp(argv[1],"-v")==0){ printf(_VERSION1); printf("\n"); exit(0); }
	if(strcmp(argv[1],"-V")==0){ printf(_VERSION); printf("\n"); exit(0); }
	return;
}

int dilca_configuration_load(char *configuration_path){
        FILE *conf_file;
        char parm_name[100],parm_val[100];

		/* Parameters initialization */
        dilca_dir_send[0] = '\0';
		dilca_dir_tmp[0]='\0';
        dilca_dir_hpsign[0]='\0';
        dilca_dir_react[0]='\0';
        dilca_polling = 1000;
        dilca_retry = 10;
        dilca_reallocation_size = 1000;

	if((conf_file=fopen(configuration_path,"rt"))==NULL){
                fprintf(stderr,"ERR - Cannot open %s conf file!\n",configuration_path);
                return false;
        }

	while(!feof(conf_file)){
                fscanf(conf_file,"%s = %99[^\n]",parm_name,parm_val);
                /* dilca_dir_hpsign = ... */
                if(strncasecmp(parm_name,"dilca_dir_hpsign",16)==0)  strcpy(dilca_dir_hpsign,parm_val);
                /* dilca_dir_send = ... */
                if(strncasecmp(parm_name,"dilca_dir_send",14)==0)  strcpy(dilca_dir_send,parm_val);
		/* dilca_dir_tmp = ... */
                if(strncasecmp(parm_name,"dilca_dir_tmp",13)==0)  strcpy(dilca_dir_tmp,parm_val);
		/* dilca_dir_react = ... */
                if(strncasecmp(parm_name,"dilca_dir_react",15)==0)  strcpy(dilca_dir_react,parm_val);
                /* dilca_retry = ... */
                if(strncasecmp(parm_name,"dilca_retry",11)==0)  sscanf(parm_val,"%d",&dilca_retry);
                /* dilca_reallocation_size = ... */
                if(strncasecmp(parm_name,"dilca_reallocation_size",23)==0) sscanf(parm_val,"%d",&dilca_reallocation_size);
                /* dilca_polling = ... */
                if(strncasecmp(parm_name,"dilca_polling",13)==0) sscanf(parm_val,"%d",&dilca_polling);
        }

        fclose(conf_file);
	
	#ifndef _WIN32
        dilca_polling *= 1000;
        #endif

	/* Parameters check */
	if((strlen(dilca_dir_react)<2) ||(strlen(dilca_dir_tmp)<2) || (strlen(dilca_dir_send)<2) ||(strlen(dilca_dir_hpsign)<2)){
		fprintf(stderr,"ERR - Directories Parameters undefined, exiting ..\n"); 
		exit(-1);
	}

	return true;
}

int dilca_crn_load(char *hosts_path, char CRN_ip[DILCA_MAX_HOSTS][255], char CRN_port[DILCA_MAX_HOSTS][255]){
        FILE *conf_file;
        int i=0;
        int res=0;
        char c;

        if((conf_file=fopen(hosts_path,"rt"))==NULL){
                fprintf(stderr,"ERR - Cannot open %s hosts file!\n",hosts_path);
                return false;
        }
        i=0;
	while(!feof(conf_file) && i < DILCA_MAX_HOSTS){
                res=fscanf(conf_file,"%s %c %99[^\n]",CRN_ip[i],&c,CRN_port[i]);
                /* ip : port */
                c == ':' ? i++ : (CRN_ip[i][0]='\0',CRN_port[i][0]='\0');
                c = '\0';
        }

        fclose(conf_file);
        return i;
}

int dilca_dir_polling(char *dir){
        struct direct **namelist;
        char rmcmd[255];
        char filename[255];
        int i,n;

        /******************************************************************/
        /** Scanning directory                                           **/
        /******************************************************************/
        while(1){
                n = scandir(dir, &namelist, 0, alphasort);
                if(n<0){
                        fprintf(stderr,"ERR - Unable to scan %s\n",dir);
                        return -1;
                }
                for(i=0;i<n;i++){
                        if(!((namelist[i]->d_name[0]=='.')&&((namelist[i]->d_name[1]=='.')||(namelist[i]->d_name[1]=='\0')))){
                                sprintf(filename,"%s%s",dir,namelist[i]->d_name);
                                dilca_file_readall(filename);
                                #ifdef _WIN32
                                snprintf(rmcmd,strlen(dir)+strlen(namelist[i]->d_name)+strlen(RMCMD)+3,"%s\"%s%s\"",RMCMD,dir,namelist[i]->d_name);
                                #else
                                snprintf(rmcmd,strlen(dir)+strlen(namelist[i]->d_name)+strlen(RMCMD)+3,"%s\"%s%s\"",RMCMD,dir,namelist[i]->d_name);
                                #endif
                                /*DBG*///DEBUG == DBG_CMD ? printf("MAIN: rmcmd _%s_\n",rmcmd) : 0;
                                system(rmcmd);
                                /*DBG*///DEBUG == DBG_FILES ? printf("%s\n",namelist[i]->d_name) : 0;
                        }
                        free(namelist[i]);
                }
                free(namelist);
                usleep(dilca_polling);
        }
}

int dilca_file_readall(char *filename){
        FILE *fp1;
        char *buff,c='a';
        int size=0,bufflen=0,realloc_cnt=0,retry=0;

        for(retry=0,fp1=fopen(filename,"rt");((fp1==NULL) && (retry<=dilca_retry));retry++,usleep(200),fp1=fopen(filename,"rt"));
        if(fp1==NULL){
                fprintf(stderr,"ERR - Cannot open %s file\n",filename);
                return -1;
        }
        size=0;realloc_cnt=0,c='a';
        buff=NULL;
        buff=(char *)calloc(sizeof(char),dilca_reallocation_size);
        realloc_cnt+=dilca_reallocation_size;
        buff[size]=fgetc(fp1);
        while(!feof(fp1)){
                if(size == realloc_cnt){
                        buff=(char*)realloc(buff,sizeof(char)*(size + dilca_reallocation_size));
                        realloc_cnt+=dilca_reallocation_size;
                }
                size++;
                buff[size]=fgetc(fp1);
        }
        buff[size]='\0';
        if(size>1) idxp_broadcast_send_message(IDXPROLE_EC,buff);
        free(buff);
        buff=NULL;
        fclose(fp1);
        return 1;
}

bool dilca_custom_function_rs(IdxpConnection *connection,IdxpChannel *channel,IdxpFrame *frame, axlPointer data){
        char filename_tmp[256];
        char filename_store[256];
        struct timeval tspc;

        #ifdef _WIN32
        win_gettimeofday(&tspc,NULL);
        #else
        gettimeofday(&tspc,NULL);
        #endif

	if(idxp_dtd_validate_frame(frame,dtd_idmef,"<signature")){
                /* Signature Received */
                snprintf(filename_tmp,strlen(dilca_dir_tmp)+26,"%s%010ld%010ld.sign",dilca_dir_tmp,tspc.tv_sec,tspc.tv_usec);
                snprintf(filename_store,strlen(dilca_dir_hpsign)+26,"%s%010ld%010ld.sign",dilca_dir_hpsign,tspc.tv_sec,tspc.tv_usec);
        }else if(idxp_dtd_validate_frame(frame,dtd_idmef,"<react")){
                /* React Received */
                snprintf(filename_tmp,strlen(dilca_dir_tmp)+27,"%s%010ld%010ld.react",dilca_dir_tmp,tspc.tv_sec,tspc.tv_usec);
                snprintf(filename_store,strlen(dilca_dir_react)+27,"%s%010ld%010ld.react",dilca_dir_react,tspc.tv_sec,tspc.tv_usec);
        } else return false;
        lightlog_idmef_write(filename_tmp,ll_INFORMATIONAL,0,(char*)idxp_frame_get_payload(frame));
        dilca_file_move(filename_store,filename_tmp);
        return true;
}


bool dilca_file_move(char *destination, char *source){
        char command[256];

        sprintf(command,"%s\"%s\" \"%s\"",MOVECMD,source,destination);
        system(command);

        return true;
}
